/*************************************************************************
	> File Name: testFW.h
	> Author: shubulan
	> Mail: gaoyulong1996@163.com
	> Created Time: Fri 16 Oct 2020 06:26:38 PM CST
 ************************************************************************/

#ifndef _TESTFW_H
#define _TESTFW_H
#include <string.h>
#include <include/listnode.h>
#define TEST(a, b)\
void a##_HAIZEI_##b();\
__attribute__((constructor))\
void add_##a##_HAIZEI_##b() {\
    add_func(a##_HAIZEI_##b, #a "." #b);\
}\
void a##_HAIZEI_##b()

#define COLOR(a, b) "\033[" #b "m" a "\033[0m"
#define HCOLOR(a, b) "\033[1;" #b "m" a "\033[0m"
#define RED(a) COLOR(a, 31)
#define HRED(a) HCOLOR(a, 31)
#define GREEN(a) COLOR(a, 32)
#define HGREEN(a) HCOLOR(a, 32)
#define BLUE(a) COLOR(a, 34)
#define HBLUE(a) HCOLOR(a, 34)
#define YELLOW(a) COLOR(a, 33)
#define HYELLOW(a) HCOLOR(a, 33)

#define TYPE(a) _Generic((a),\
    int : "%d",\
    double : "%lf",\
    float : "%lf",\
    long long : "%lld",\
    const char * : "%s",\
    char * : "%s"\
)

#define P(a, color) {\
    char fmt[1000];\
    sprintf(fmt, color("%s"), TYPE(a));\
    printf(fmt, a);\
}
#define EXPECT(a, b, comp) {\
    __typeof(a) _a = (a);\
    __typeof(b) _b = (b);\
    testInfo.total += 1;\
    if (_a comp _b) {\
        testInfo.success += 1;\
    } else {\
        printf(HYELLOW("\n\t%s:%d: Failure\n"), __FILE__, __LINE__);\
        printf(HYELLOW("\t\texpect : " #a " " #comp " " #b "\n"));\
        printf(HYELLOW("\t\tactual : "));\
        P(_a, HYELLOW);\
        P(" vs ", HYELLOW);\
        P(_b, HYELLOW);\
        printf("\n\n");\
    }\
    printf(GREEN("[-----------] "));\
    printf(#a " " #comp " " #b " ");\
    printf("%s\n", _a comp _b ? GREEN("True") : HRED("False"));\
}

#define EXPECT_EQ(a, b) EXPECT(a, b, ==)
#define EXPECT_NE(a, b) EXPECT(a, b, !=)
#define EXPECT_GE(a, b) EXPECT(a, b, >=)
#define EXPECT_GT(a, b) EXPECT(a, b, >)
#define EXPECT_LE(a, b) EXPECT(a, b, <=)
#define EXPECT_LT(a, b) EXPECT(a, b, <)

typedef void (*FuncType)();

typedef struct {
    FuncType func;
    const char * funcName;
    struct LinkNode next;
} FuncStruc;
struct funcInfo {
    int total, success;
};
extern struct funcInfo testInfo; 
int RUN_ALL_TESTS();
void add_func(FuncType, const char*);
#endif
